/*
 *      Author: Guannan Ma
 *      @mythmgn
 *      Whatever license applied
 */

#include <fcntl.h>

#if defined __linux__
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif

#include "base.h"

inline int setNonBlockingFD(int fd) {
	if (fd < 0 || 0 == fd)
		return FALSE;
	else {
		if (-1 == fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK)) {
			return FALSE;
		} else
			return TRUE;
	}
}

inline BOOL setTcpSocketKeepAlive(SOCKET s, int idle, int intvl, int count) {
	ASSERT(s >= 0);
	ASSERT(idle > 0);
	ASSERT(intvl > 0);
	ASSERT(count > 0);

	int keepAlive = 1;
	if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*) &keepAlive,
			sizeof(keepAlive)) == -1) {
		return FALSE;
	}
	/* IPPROTO_TCP is in netinet/in.h*/
	if (setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, (void *) &idle, sizeof(idle))
			== -1) {
		return FALSE;
	}

	if (setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &intvl,
			sizeof(intvl)) == -1) {
		return FALSE;
	}

	if (setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, (void *) &count, sizeof(count))
			== -1) {
		return FALSE;
	}
	return TRUE;
}

inline BOOL
setSocketLingerOff(SOCKET s)
{
    struct linger lingr = { 0, 0 };
    if (0 == setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&lingr, sizeof(lingr)))
        return TRUE;
    return FALSE;
}

inline BOOL
setSocketReuseAddr(SOCKET s)
{
    int flag = 1;
    if (0 == setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)))
        return TRUE;
    return FALSE;
}

inline BOOL
setSocketNoDelay(SOCKET s)
{
    int flag = 1;
    if (0 == setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)))
        return TRUE;
    return FALSE;
}

inline BOOL
setSocketQuickAck(SOCKET s, BOOL enable)
{
    int flag = enable ==TRUE ? 1 : 0;
    if (0 == setsockopt(s, IPPROTO_TCP, TCP_QUICKACK, (char *)&flag, sizeof(flag)))
        return TRUE;
    return FALSE;
}
